// -----------------------------------------------------------------------------
// This source file is part of Matrix Platform
// 	(Universal .NET Software Development Platform)
// For the latest info, see http://www.matrixplatform.com
// 
// Copyright (c) 2009-2010, Ingenious Ltd
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// -----------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Windows.Forms;

namespace Matrix.Common.FrontEnd
{
    /// <summary>
    /// Helps in persisting objects. Provides surrogate selectors for serializing
    /// non serializables like Pen, Brush, etc.
    /// </summary>
    public class UISerializationHelper
    {
        ///// <summary>
        ///// This is an extremely partial state persistence, does not include contained control.
        ///// </summary>
        //public class DragControlSurrogate : ISerializationSurrogate
        //{
        //    public void GetObjectData(object obj, SerializationInfo info, StreamingContext context)
        //    {
        //        DragControl control = (DragControl)obj;
        //        info.AddValue("location", control.Location);
        //        info.AddValue("text", control.Text);
        //        info.AddValue("name", control.Name);
        //        info.AddValue("dock", control.Dock);
        //    }

        //    public object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
        //    {
        //        DragControl control = new DragControl();
        //        control.Location = (Point)info.GetValue("location", typeof(Point));
        //        control.Text = info.GetString("text");
        //        control.Name = info.GetString("name");
        //        control.Dock = (DockStyle)info.GetValue("dock", typeof(DockStyle));
                
        //        return control;
        //    }

        //}


        //public static IFormatter GenerateFormatter()
        //{
        //    // 1. Construct the desired formatter
        //    IFormatter formatter = new BinaryFormatter();

        //    // 2. Construct a SurrogateSelector object
        //    SurrogateSelector surrogateSelector = new SurrogateSelector();

        //    // 3. Tell the surrogate selector to use our object when a 
        //    // object is serialized/deserialized
        //    //surrogateSelector.AddSurrogate(typeof(Color),
        //    //   new StreamingContext(StreamingContextStates.All),
        //    //   new ColorSurrogate());

        //    //surrogateSelector.AddSurrogate(typeof(DragControl),
        //    //   new StreamingContext(StreamingContextStates.All),
        //    //   new MatrixSurrogate());

        //    surrogateSelector.AddSurrogate(typeof(Matrix),
        //       new StreamingContext(StreamingContextStates.All),
        //       new MatrixSurrogate());

        //    surrogateSelector.AddSurrogate(typeof(Pen),
        //       new StreamingContext(StreamingContextStates.All),
        //       new PenSurrogate());

        //    surrogateSelector.AddSurrogate(typeof(SolidBrush),
        //       new StreamingContext(StreamingContextStates.All),
        //       new SolidBrushSurrogate());

        //    surrogateSelector.AddSurrogate(typeof(LinearGradientBrush),
        //       new StreamingContext(StreamingContextStates.All),
        //       new LinearGradientBrushSurrogate());

        //    surrogateSelector.AddSurrogate(typeof(Blend),
        //       new StreamingContext(StreamingContextStates.All),
        //       new BlendSurrogate());

        //    surrogateSelector.AddSurrogate(typeof(ColorBlend),
        //       new StreamingContext(StreamingContextStates.All),
        //       new ColorBlendSurrogate());

        //    formatter.SurrogateSelector = surrogateSelector;

        //    return formatter;
        //}


        ///// <summary>
        ///// Special helper for doing data from a SerializationInfo.
        ///// </summary>
        //public static void SerializeInfo(Stream stream, SerializationInfo info)
        //{
        //    try
        //    {
        //        IFormatter formatter = GenerateFormatter();

        //        SerializationInfoEnumerator enumerator = info.GetEnumerator();
        //        while (enumerator.MoveNext())
        //        {
        //            formatter.SaveState(stream, enumerator.Current.Name);
        //            formatter.SaveState(stream, enumerator.Current.Value);
        //        }
        //    }
        //    catch (Exception ex)
        //    {
        //        SystemMonitor.Error("Failed to serialize info [" + ex.Message + "].");
        //    }
        //}

        ///// <summary>
        ///// Special helper for doing data from a SerializationInfo.
        ///// </summary>
        //public static void DeSerializeInfo(SerializationInfo info, Stream stream)
        //{
        //    try
        //    {
        //        IFormatter formatter = GenerateFormatter();

        //        string name;
        //        do
        //        {
        //            name = (string)formatter.Deserialize(stream);
        //            object value = formatter.Deserialize(stream);
        //            info.AddValue(name, value);
        //        }
        //        while (string.IsNullOrEmpty(name) == false);
        //    }
        //    catch (Exception ex)
        //    {
        //        SystemMonitor.Error("Failed to serialize info [" + ex.Message + "].");
        //    }
        //}


        public static void ManualSerialize(Dictionary<string, Pen> pens, SerializationInfo info)
        {
            // There are problems with serializing arrays of pens (they require a single pen to also be serialized to reference the Pen surrogate or something).
            // so this model of serialization is used.
            info.AddValue("outResultPenCount", pens.Count);
            int index = 0;
            foreach (string name in pens.Keys)
            {
                info.AddValue("outResultPenName." + index.ToString(), name);
                info.AddValue("outResultPen." + index.ToString(), pens[name]);
                index++;
            }
        }

        public static void ManualDeSerialize(SerializationInfo info, Dictionary<string, Pen> pens)
        {
            // There are problems with serializing arrays of pens (they require a single pen to also be serialized to reference the Pen surrogate or something).
            // so this model of serialization is used.
            int penCount = info.GetInt32("outResultPenCount");
            for (int i = 0; i < penCount; i++)
            {
                string name = info.GetString("outResultPenName." + i.ToString());
                Pen pen = (Pen)info.GetValue("outResultPen." + i.ToString(), typeof(Pen));
                pens.Add(name, pen);
            }
        }

        /// <summary>
        /// Color surrogate does not work (it is a reference type, so this might be the problem).
        /// </summary>
        public static void ManualSerialize(string name, Color color, SerializationInfo info)
        {
            info.AddValue(name, color.ToArgb());
        }

        public static void ManualDeSerialize(SerializationInfo info, string name, out Color color)
        {
            color = Color.FromArgb(info.GetInt32(name));
        }
    }
}
